
#include "stdafx.h"
#include "ConstDef.h"
#include "ReloadCode.h"
#include "ReloadDebugPacket.h"
#include "ReloadDebugerApp.h"

ReloadDebugerAppConfigure::ReloadDebugerAppConfigure()
{

}

ReloadDebugerAppConfigure::~ReloadDebugerAppConfigure()
{

}

retT ReloadDebugerAppConfigure::init( const std::string _configFileName/*=DEFAULT_CONFIG_FILE_NAME*/ )
{
	RNL(asyframe::ConfigureBase::init(RELOAD_DEBUGER_CONFIG_FILE_NAME));
	try
	{
		instanceName_ = pt_.get<std::string>("Config.ReloadDebuger.instanceName");
		debugPort_ = pt_.get<unsigned short>("Config.ReloadDebuger.debugPort");
	}
	catch(std::exception *)
	{
		return ERROR_APPBASE_INIT_READ_CONFIG_FAIL;
	}
	RETSUCCESSNL;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

ReloadDebugerApp::ReloadDebugerApp( asyframe::ConfigureBase* _pConfigure /*= new asyframe::ConfigureBase()*/ )
:asyframe::AppBase(_pConfigure),cmd_(ReloadDebugCmd_Invalid),pRemoteEndpoint_()
{

}

ReloadDebugerApp::~ReloadDebugerApp()
{
	cmd_ = ReloadDebugCmd_Invalid;
	pRemoteEndpoint_.reset();
}

retT ReloadDebugerApp::initInstance( int argc, char* argv[] )
{
	R(asyframe::AppBase::initInstance(argc, argv));
	if(argc != 3)
	{
		std::cout << "ReloadDebuger cmd ip" << std::endl;
		RETSUCCESSNL;
	}
	cmd_ = boost::lexical_cast<int>(argv[1]);
	pRemoteEndpoint_.reset(new boost::asio::ip::udp::endpoint(
		boost::asio::ip::address::from_string(argv[2]),
		((ReloadDebugerAppConfigure*)asyframe::getApp()->getConfigure())->debugPort_));
	RETSUCCESS;
}

retT ReloadDebugerApp::init()
{
	R(asyframe::AppBase::init());
	pUdpHandler_.reset(new asyframe::UdpHandler());
	boost::shared_ptr<boost::asio::ip::udp::endpoint> pLocalEndpoint(new boost::asio::ip::udp::endpoint(
		boost::asio::ip::udp::v4(), ((ReloadDebugerAppConfigure*)asyframe::getApp()->getConfigure())->debugPort_ + 10));
	pUdpHandler_->setLocalEndpoint(pLocalEndpoint);
	R(pUdpHandler_->attachHandlerOwner(shared_from_this()));
	RETSUCCESS;
}

retT ReloadDebugerApp::start()
{
	R(asyframe::AppBase::start());
	if(cmd_ == ReloadDebugCmd_Invalid)
	{
		R(stop());
		RETSUCCESS;
	}
	if(boost::shared_ptr<asyframe::WorkerBase> pWorker = getWorker())
	{
		boost::shared_ptr<asyframe::UdpHandlerContext> pUdpHandlerContext(new asyframe::UdpHandlerContext());
		boost::shared_ptr<asyframe::IoBuffer> pBuffer(new asyframe::IoBuffer(pWorker, maxReloadDebugMessageSize));
		pUdpHandlerContext->pTimerDuration_.reset(new boost::posix_time::seconds(RELOAD_DEBUG_WAIT_RESPONSE_SECONDS));
		pUdpHandlerContext->bytesToTransfer_ = maxReloadDebugMessageSize;
		pUdpHandlerContext->pRemoteEndpoint_.reset(new boost::asio::ip::udp::endpoint());
		R(pUdpHandler_->asyncReadFrom(pBuffer, pUdpHandlerContext->pRemoteEndpoint_, pUdpHandlerContext,
			boost::bind(&ReloadDebugerApp::onReadReloadDebugResponse, boost::dynamic_pointer_cast<ReloadDebugerApp>(shared_from_this()),
			pUdpHandlerContext, _1, _2, _3)));
	}
	else
		RET(ERROR_COMMON_SHARED_PTR_NULL);

	if(boost::shared_ptr<asyframe::WorkerBase> pWorker = getWorker())
	{
		boost::shared_ptr<asyframe::UdpHandlerContext> pUdpHandlerContext(new asyframe::UdpHandlerContext());
		boost::shared_ptr<asyframe::IoBuffer> pBuffer(new asyframe::IoBuffer(pWorker));
		R(pBuffer->write(cmd_));
		R(pUdpHandler_->asyncWriteTo(pBuffer, pRemoteEndpoint_, pUdpHandlerContext, boost::bind(
			&ReloadDebugerApp::onSendCmd, boost::dynamic_pointer_cast<ReloadDebugerApp>(shared_from_this()),
			pUdpHandlerContext, _1, _2, _3)));
	}
	else
		RET(ERROR_COMMON_SHARED_PTR_NULL);
	RETSUCCESS;
}

retT ReloadDebugerApp::onSendCmd( boost::shared_ptr<asyframe::UdpHandlerContext> _pUdpHandlerContext, std::size_t _bytesTransferred, const boost::system::error_code& e, std::size_t _timeoutCount )
{
	R(asyframe::IUdpAction::onWriteTo(_pUdpHandlerContext, _bytesTransferred, e, _timeoutCount));
	if(!e)
	{
		if(_pUdpHandlerContext && _pUdpHandlerContext->pHandler_)
		{

		}
	}
	else
	{
		LOG_INFO(boost::format( "errorNo %1% : %2% in %3% %4% %5%" ) % e.value() % e.message() % __FUNCTION__ % __FILE__ % __LINE__);
		R(stop());
	}
	RETSUCCESS;
}

retT ReloadDebugerApp::onReadReloadDebugResponse( boost::shared_ptr<asyframe::UdpHandlerContext> _pUdpHandlerContext, std::size_t _bytesTransferred, const boost::system::error_code& e, std::size_t _timeoutCount )
{
	R(asyframe::IUdpAction::onReadFrom(_pUdpHandlerContext, _bytesTransferred, e, _timeoutCount));
	if(!e)
	{
		if(_pUdpHandlerContext && _pUdpHandlerContext->pRemoteEndpoint_)
		{
			R(_pUdpHandlerContext->reset());
			if(_timeoutCount == 0)
			{
				if(_pUdpHandlerContext->pBuffer_)
				{
					parseCmd(_pUdpHandlerContext->pBuffer_);
					R(stop());
				}
			}
			else
			{
				LOG_INFO(boost::format( "Request timeout in %1% %2% %3%" ) % __FUNCTION__ % __FILE__ % __LINE__);
				R(stop());
			}
		}
	}
	else
	{
		LOG_INFO(boost::format( "errorNo %1% : %2% in %3% %4% %5%" ) % e.value() % e.message() % __FUNCTION__ % __FILE__ % __LINE__);
		R(stop());
	}
	RETSUCCESS;
}

retT ReloadDebugerApp::parseCmd( boost::shared_ptr<asyframe::IoBuffer> _pBuffer )
{
	switch(cmd_)
	{
	case ReloadDebugCmd_ChordInfo:R(parseChordInfo(_pBuffer));break;
	case ReloadDebugCmd_DataStorageInfo:R(parseDataStorageInfo(_pBuffer));break;
	default:break;
	}
	RETSUCCESS;
}

retT ReloadDebugerApp::parseChordInfo(boost::shared_ptr<asyframe::IoBuffer> _pBuffer)
{
	ChordInfoDebugPacket chordInfoDebugPacket;
	R(chordInfoDebugPacket.readFromBuffer(_pBuffer));
	std::cout << "NodeInfo: " << "[";
	std::cout << chordInfoDebugPacket.selfNodeInfo_.nodeId_.toString() << " ";
	std::cout << chordInfoDebugPacket.selfNodeInfo_.ipAddressPort_.addr_.to_string() << " ";
	std::cout << chordInfoDebugPacket.selfNodeInfo_.ipAddressPort_.port_ << "]" << std::endl << std::endl;

	std::cout << "Predecessors[" << chordInfoDebugPacket.predecessors_.array_.size() << "]:" << std::endl;
	for(std::size_t i = 0; i < chordInfoDebugPacket.predecessors_.array_.size(); ++i)
	{
		std::cout << "Predecessor[" << i << "]: [";
		std::cout << chordInfoDebugPacket.predecessors_.array_[i].nodeId_.toString() << " ";
		std::cout << chordInfoDebugPacket.predecessors_.array_[i].ipAddressPort_.addr_.to_string() << " ";
		std::cout << chordInfoDebugPacket.predecessors_.array_[i].ipAddressPort_.port_ << "]" << std::endl;
	}
	std::cout << std::endl;

	std::cout << "Successors[" << chordInfoDebugPacket.successors_.array_.size() << "]:" << std::endl;
	for(std::size_t i = 0; i < chordInfoDebugPacket.successors_.array_.size(); ++i)
	{
		std::cout << "Successor[" << i << "]: [";
		std::cout << chordInfoDebugPacket.successors_.array_[i].nodeId_.toString() << " ";
		std::cout << chordInfoDebugPacket.successors_.array_[i].ipAddressPort_.addr_.to_string() << " ";
		std::cout << chordInfoDebugPacket.successors_.array_[i].ipAddressPort_.port_ << "]" << std::endl;
	}
	std::cout << std::endl;

	std::cout << "FingerTable[" << chordInfoDebugPacket.fingers_.array_.size() << "]:" << std::endl;
	for(std::size_t i = 0; i < chordInfoDebugPacket.fingers_.array_.size(); ++i)
	{
		std::cout << "Fingers[" << i << "][" << chordInfoDebugPacket.fingers_.array_[i].array_.size() << "]:" << std::endl;
		for(std::size_t j = 0; j < chordInfoDebugPacket.fingers_.array_[i].array_.size(); ++j)
		{
			std::cout << "Finger[" << i << "][" << j << "]: [";
			std::cout << chordInfoDebugPacket.fingers_.array_[i].array_[j].nodeId_.toString() << " ";
			std::cout << chordInfoDebugPacket.fingers_.array_[i].array_[j].ipAddressPort_.addr_.to_string() << " ";
			std::cout << chordInfoDebugPacket.fingers_.array_[i].array_[j].ipAddressPort_.port_ << "]" << std::endl;
		}
	}
	RETSUCCESS;
}

retT ReloadDebugerApp::parseDataStorageInfo( boost::shared_ptr<asyframe::IoBuffer> _pBuffer )
{
	DataStorageInfoDebugPacket dataStorageInfoDebugPacket;
	R(dataStorageInfoDebugPacket.readFromBuffer(_pBuffer));
	std::cout << "nonReplica:" << dataStorageInfoDebugPacket.nonReplica_;
	std::cout << " replica1:" << dataStorageInfoDebugPacket.replica1_;
	std::cout << " replica2:" << dataStorageInfoDebugPacket.replica2_;
	std::cout << " unknownReplica:" << dataStorageInfoDebugPacket.unknownReplica_;
	std::cout << " total:" << dataStorageInfoDebugPacket.nonReplica_+ dataStorageInfoDebugPacket.replica1_ + dataStorageInfoDebugPacket.replica2_ + dataStorageInfoDebugPacket.unknownReplica_;
	std::cout << std::endl;
	RETSUCCESS;
}
